home *** CD-ROM | disk | FTP | other *** search
- u
- DIRECTORY TO BASIC
- by Dave Moorman
-
-
- There are two ways to bring a
- directory into Basic that I won't use
- today. The first is to load up a good
- toolbox module such as MR.MOUSE and
- use its Directory features. But for
- this tutorial, I want to show a
- couple of things. So we will
- "re-invent" the wheel -- so to speak.
-
- The other method is to OPEN the
- directory with an OPEN statement, then
- use GET# to bring in the text, one
- character at a time. This oft touted
- technique has two problems:
-
- 1. It is slower than molasses on a
- cold morning, and
-
- 2. It uses string concatenation, which
- I would rather avoid as much as
- possible.
-
- As an alternative, I will Bload
- the directory into memory. To put the
- bytes into a string, I will show a
- much faster method.
-
- The program here is designed to go
- through a disk directory looking for
- files with "L/D." prefixes and Rename
- them to have "LD." prefixes. This is
- in response to the problem Stephen
- Beigle found after using Letter Drop
- Writer to create quotes for Letter
- Drop. Writer saves files with "L/D."
- prefixes, while Letter Drop reads only
- files with "LD." prefixes.
-
- So, if you don't want to learn
- anything, just run the Run It program.
- At the prompt, put a disk full of
- Letter Drop Writer quotes (L/D.) in a
- drive and choose the drive number from
- the menu. In a minute, your files will
- all be renamed.
-
- However, if you want to find out
- how it is done, stick around!
-
-
- THE PROGRAM
-
- The first lines are fairly
- standard around the Tower.
-
- 5 IFPEEK(56)<>64THENPOKE56,64:RUN
-
- This line sets the Top of Basic to
- Page 64, giving a lot of free memory
- for the Directory.
-
- 10 D=PEEK(186):IFD<8THENSTOP
-
- Of course, make D the current
- device. On the Run It version, I added
- a Menu to allow changing disks.
-
- 20 DEFFNH(X)=INT(X/256)
- 21 DEFFNL(X)=X-FNH(X)*256
-
- These two defined functions will
- divide a memory location into two
- bytes. There are lots of ways of doing
- this. I think it is more elegant to
- use FNH(x) and FNL(x) in the body of
- the program.
-
-
- 100 REM MAKE A$ A MOVEABLE STRING
- 101 A$=STR$(PEEK(71)+256*PEEK(72))
- 102 A=VAL(A$)
-
- Now this bit of code may look odd.
- String variables do not directly hold
- their string content. They are set up
- right along with all other variables,
- with two bytes for the variable name
- and five bytes for content. Strings
- only use three of the five bytes --
- for Length, Address Low, and Address
- Hi. These two Address bytes point to
- the actual contents of the variable.
-
- Back when I used my TRS-80 Model
- I, Level II Basic (also by Microsoft),
- I found a function called STRPTR(v),
- which returned the first byte of the
- three-byte pointer for variable v.
- Alas, Basic 2.0 does not have STRPTR.
- But we do have a very well explored
- zero page. And the variable pointers
- are pointed to by locations 71/72.
-
- Now the pointer pointer is a very
- busy place. Capturing the value there
- is tricky, especially for string
- variables. So I found a dodge. (I
- wanted a Plymouth, but a Dodge will
- do!) Look carefully above. The value
- in 71/72 is put in a STR$ and put into
- A$. That value is the location of the
- A$s pointer. I put the VAL(A$) into A,
- and now
-
- A holds LENGTH
- A+1 holds the LO BYTE
- A+2 holds the HI BYTE
-
- The beautiful thing about how a
- Microsoft Basic handles string
- variable is that when you POKE values
- into these three bytes, A$ will
- "contain" whatever A bytes start at
- A+1/A+2. You can't look under ROM with
- this, but any other memory can be very
- quickly grabbed into a string
- variable.
-
- 110 F$="L/D.":F=LEN(F$)+1:REM FIND STR
- ING
- 120 T$="LD.":T=LEN(T$)+1:REM TO STRING
-
- To simplify the code, I put the
- FROM prefix in F$ and the TO prefix
- into T$, with F and T holding the
- length of each (plus 1). As I was
- testing, I could easily swap the two
- patterns, changing the disk from
- "L/D." files to "LD." files and vice
- versa.
-
-
- 149 REM BLOAD DIRECTORY
- 150 SYS57812"$:"+F$+"*",D,0:POKE780,0
- :POKE781,0:POKE782,64 :SYS65493
-
- If you don't have this code all
- but memorized, you haven't done enough
- programming! To Bload a directory in a
- format you can read, be sure the
- secondary address (the ,0) is 0.
-
-
- 159 REM BEGIN AT 64*256 & SKIP HEADER
- 160 L=64*256+32
- 161 L1=2 :REM SKIP 2 BYTES
- 162 L2=16 :REM LENGTH OF FILENAME
-
- Once the directory is in memory at
- Page 64, we need to point to it. Note
- -- I [think] in memory pages, which is
- why I use 64*256. Who can remember
- every page's full memory number?
- Also, in this situation, the Header is
- not needed, so we add 32 in order to
- just skip it.
-
- L1 is set to 2 because the first
- two bytes of a directory line hold the
- block count as a two-byte integer. We
- are going to skip these. However, if
- you want to get the block size, use
- the following:
-
- DEFFNI(X)=PEEK(X)+256*PEEK(X+1)
-
- BS=FNI(L)
-
- BS will hold the Block Size of the
- file.
-
-
- 163 REM CHECK FOR "BLOCK" --END OF DIR
- 164 POKEA,5:POKEA+1,FNL(L+L1):POKEA+2,
- FNH(L+L1):IFA$="BLOCK"THENEND
-
- Any good processing program must
- know when to quit. With a directory,
- when you get to BLOCKS FREE, you know
- you are done. So here we use the
- A$-Gambit. We need a 5 byte long
- string, beginning with location L+L1.
- By POKEing the Length, LOW, and HIGH
- into A, A+1, A+2, we make A$ "look" at
- the particular directory line.
-
-
- 169 REM FIND FIRST QUOTE MARKS
- 170 IFPEEK(L+L1)<>34THENL1=L1+1:
- GOTO170
- 175 L1=L1+1
-
- Long ago, in the ancient days of
- the PET, someone at Microsoft decided
- to save some precious ROM by using the
- LIST routine to display the Directory.
- It was a clever answer for 1976. Then
- CBM built the C-64 in an unprecidented
- [TWO MONTHS], and to get the machine
- out the door, they just copied Basic
- 2.0. This is why the Block Size is a
- two-byte value rather than the actual
- numbers.
-
- When you LIST the Directory, the
- Line Number routine generates the
- Block Size. But in order to have the
- Filenames line up nice and straight,
- some Space characters are used to pad
- the line before the quote mark. Nice
- for them -- a pain for us! In line 170
- above, L1 in incremented until a quote
- (34) is found, then incremented once
- more. L+L1 now points to the beginning
- of the filename.
-
-
- 179 REM FIND LENGTH TO 2ND QUOTE MARKS
- 180 IFPEEK(L+L1+L2)<>34THENL2=L2-1:GOT
- o180
-
- Likewise, the filename might be 16
- characters long -- or not. So we
- decrement L2 to find the end quote
- marks.
-
-
- 189 REM POKE LEN, LO, HI INTO A
- 190 POKEA,L2:POKEA+1,FNL(L+L1):POKEA+2
- ,FNH(L+L1)
-
- Once we have the Length and
- Location of the text, we can POKE the
- values into the A$ pointer.
-
-
- 191 REM SCRUB OFF PREFIX
- 192 A$=MID$(A$,F):PRINTA$
-
- Now, I [could] have just added 5
- to L+L1 in line 90. This is more
- transparent. We remove the prefix from
- A$.
-
-
- 193 REM RENAME TO NEW PREFIX
- 194 OPEN15,D,15,"R0:"+T$+A$+"="+F$+A$:
- CLOSE15
-
- And finally, we can do the Rename.
- All that work for just one functional
- line! On the otherhand, you could do
- all the Renames in Immediate Mode,
- like Stephen did.
-
-
- 198 REM ADD 32 TO LOCATION
- 199 L=L+32:GOTO161
- 999 end
-
- And lastly, we add 32 to L to
- point to the next line, and go to line
- 161 to do it again.
-
-
- 10000 D=PEEK(186):N$="B.DIR TO BAS":
- OPEN1,D,15,"I0":CLOSE1
- 10001 OPEN1,D,15,"S0:"+N$:CLOSE1:
- SAVEN$,D:END
-
- I wanted to show you how I now do
- the Scratch and Save routine. The "I0"
- is just a safety measure, making sure
- the drive is set and ready to work
- right. I have had a couple of
- "accidents" that could have been
- solved by using this one more disk
- command.
-
- Well, that's it. I never cease to
- be amazed at how ingenius and
- club-footed Basic 2.0 is! But since
- everything is [always] logical, one
- can logically get around any problem!
-
- DMM
-
-
-